package com.wfm.mianshi.生产消费模型;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class 利用非线程安全队列加ReentrantLock {

    // 共享资源类
    static class SharedResourceWithLock {
        private final Queue<Integer> queue = new LinkedList<>();
        private static final int MAX_SIZE = 5;
        private final ReentrantLock lock = new ReentrantLock();
        private final Condition notFull = lock.newCondition();
        private final Condition notEmpty = lock.newCondition();

        // 生产者方法
        public void produce(int item) throws InterruptedException {
            lock.lock();
            try {
                while (queue.size() == MAX_SIZE) {
                    // 队列已满，生产者等待
                    notFull.await();
                }
                queue.add(item);
                System.out.println("生产者生产: " + item);
                // 通知消费者有新数据
                notEmpty.signal();
            } finally {
                lock.unlock();
            }
        }

        // 消费者方法
        public int consume() throws InterruptedException {
            lock.lock();
            try {
                while (queue.isEmpty()) {
                    // 队列为空，消费者等待
                    notEmpty.await();
                }
                int item = queue.poll();
                System.out.println("消费者消费: " + item);
                // 通知生产者有空间可用
                notFull.signal();
                return item;
            } finally {
                lock.unlock();
            }
        }
    }

    // 生产者类
    static class ProducerWithLock implements Runnable {
        private final SharedResourceWithLock sharedResource;

        public ProducerWithLock(SharedResourceWithLock sharedResource) {
            this.sharedResource = sharedResource;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    sharedResource.produce(i);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    // 消费者类
    static class ConsumerWithLock implements Runnable {
        private final SharedResourceWithLock sharedResource;

        public ConsumerWithLock(SharedResourceWithLock sharedResource) {
            this.sharedResource = sharedResource;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    sharedResource.consume();
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    public static void main(String[] args) {
        SharedResourceWithLock sharedResource = new SharedResourceWithLock();
        Thread producerThread = new Thread(new ProducerWithLock(sharedResource));
        Thread consumerThread = new Thread(new ConsumerWithLock(sharedResource));

        producerThread.start();
        consumerThread.start();

        try {
            producerThread.join();
            consumerThread.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}
